classdef GObject < glib.GThing

  properties (Constant)
    NULL = glib.GObject(uint32(0), uint64(0), glib.GClass.NULL)
  end

  properties
    class = glib.GClass.NULL
    knownProps__
  end

  methods (Static=true)
    function obj = new(type, varargin)
      if ~ isa(type, 'glib.GClass')
        error('GObject:new', 'Not a valid GClass')
      end
      obj = glib.g_object_matlab_new(type, varargin);
    end
  end  %% Static Methods

  methods
    function varargout = subsref(obj, S, noutrequested)
      if nargin < 3
        noutrequested = nargout;
        indirectReturn = false;
      else
        if nargout > 1, error 'Too many outputs for indirect return', end
        indirectReturn = true;
      end
      if length(S) > 2, error 'Too many subscripts for GObject', end
      if ~strcmp(S(1).type, '.'), error 'Unsupported subscript', end
      name = S(1).subs;
      if length(S) == 1   % First look for property
        if noutrequested > 1, error 'Too many outputs for GObject member', end
        if ~obj.knownProps__.isKey(name) && glib.g_object_matlab_has_property(obj.value, name)
          obj.knownProps__(name) = true;
        end
        if obj.knownProps__.isKey(name)
          ret = glib.g_object_matlab_get_property(obj.value, name);
          if indirectReturn, varargout{1} = { ret };
          else varargout{1} = ret; end
        else  % Try for a method
          ret = subsref(obj.class, S);
          if indirectReturn, varargout{1} = { ret };
          else varargout{1} = ret; end
        end
      else  % Call the method
        S(2).subs = { obj S(2).subs{:} };
        ret = subsref(obj.class, S, noutrequested);
        if indirectReturn, varargout{1} = ret;
        else varargout = ret; end
      end % only 1 subscript?
    end  % function subsref

    function obj = subsasgn(obj, S, value)
      if length(S) > 1, error 'Too many subscripts for assignment', end
      if ~strcmp(S.type, '.'), error 'Unsupported subscript for assignment', end
      glib.g_object_matlab_set_property(obj.value, S.subs, value);
    end  % function subsasgn

    function signal_connect(obj, signal, func, data, after)
      switch nargin
        case 3
          glib.g_signal_connect(obj.value, signal, func);
        case 4
          glib.g_signal_connect(obj.value, signal, func, data);
        case 5
          glib.g_signal_connect(obj.value, signal, func, data, after);
        otherwise
          error 'Incorrect number of arguments to signal_connect'
      end
    end

    %% This is an internal constructor!
    %% To create a GObject, call the GType object
    %% or use glib.GObject.new()
    function obj = GObject(gtype, ptr, cls)
      if nargin == 0
        obj = glib.GObject.NULL;
      else
        obj.gtype = gtype;
        obj.value = ptr;
        obj.class = cls;
        obj.knownProps__ = containers.Map;
      end
    end

    function delete(obj)
      if obj.value
        glib.g_object_matlab_release(obj.value);
      end
    end

    function s = char(obj)
      s = sprintf('[%s as %s at 0x%lx]', char(obj.class), name(obj.class), uint64(obj.value));
    end

  end  % Public Methods

end  % Classdef
